import { QUIView } from "./QUIView";
import QGamePlugin from "./QGamePlugin";

export type QUIGridConfig = {
    id?: string;
    class?: string;
    widthRatio?: number;
    heightRatio?: number;
    width?: number;
    height?: number;
    miniWidth?: number;
    miniHeight?: number;
    maxWidth?: number;
    maxHeight?: number;
    left?: number;
    top?: number;
    background?: number | string;
    borderColor?: number | string;
    borderWidth?: number;
    aplpha?: number;
};

export class QUIGridLayout extends QUIView {
    protected name: string = "QUIGridLayout";
    constructor(
        scene: Phaser.Scene,
        manage: QGamePlugin,
        config?: QUIGridConfig
    ) {
        super(scene, manage, config);
    }

    private calcWidth(row: QUIView[]): number {
        if (row.length == 0) {
            return 0;
        }

        if (row.length == 1) {
            return row[0].Width;
        }
        if (row.length >= 2) {
            return (
                row[row.length - 1].Left +
                row[row.length - 1].Width -
                row[0].Left
            );
        }
        return 0;
    }

    private calcHeight(row: QUIView[]): number {
        if (row.length == 0) {
            return 0;
        }

        if (row.length > 0) {
            let maxHeight = 0;
            for (let i = 0; i < row.length; i++) {
                const view = row[i];
                if (view.Height > maxHeight) {
                    maxHeight = view.Height;
                }
            }
            return maxHeight;
        }
        return 0;
    }

    // private calcHeight(row: QUIView[]): number {}

    reLayout(): void {
        // 实现inline-block布局

        // alignY：top, alignX：left, 从左上角开始，超出范围时换行
        if (this.alignX == "left" && this.alignY == "top") {
            let offsetX = this.paddingLeft;
            let offsetY = this.paddingTop;
            let maxHeight = 0;
            for (let i = 0; i < this.childViews.length; i++) {
                const view = this.childViews[i];
                view.Top = offsetY;
                view.Left = offsetX;
                offsetX += view.Width + this.gap;
                let tempMaxWidth = maxHeight;
                if (view.Height > maxHeight) {
                    maxHeight = view.Height;
                }
                if (
                    offsetX > this.Width - this.paddingRight &&
                    offsetX - this.gap > this.Width - this.paddingRight
                ) {
                    i--;
                    offsetX = this.paddingLeft;
                    if (tempMaxWidth != maxHeight) {
                        maxHeight = tempMaxWidth;
                    }
                    offsetY += maxHeight + this.gap;
                    maxHeight = 0;
                    continue;
                }
                if (offsetX >= this.Width - this.paddingRight) {
                    offsetX = this.paddingLeft;
                    offsetY += maxHeight + this.gap;
                    maxHeight = 0;
                }
            }
        } else if (this.alignX == "right" && this.alignY == "top") {
            let offsetX = this.Width - this.paddingRight;
            let offsetY = this.paddingTop;
            let maxHeight = 0;
            for (let i = 0; i < this.childViews.length; i++) {
                const view = this.childViews[i];
                view.Top = offsetY;
                view.Left = offsetX - view.Width;
                offsetX -= view.Width + this.gap;
                let tempMaxWidth = maxHeight;
                if (view.Height > maxHeight) {
                    maxHeight = view.Height;
                }
                if (
                    offsetX < this.paddingLeft &&
                    offsetX + this.gap < this.paddingLeft
                ) {
                    i--;
                    offsetX = this.Width - this.paddingRight;
                    if (tempMaxWidth != maxHeight) {
                        maxHeight = tempMaxWidth;
                    }
                    offsetY += maxHeight + this.gap;
                    maxHeight = 0;
                    continue;
                }
                if (offsetX <= this.paddingLeft) {
                    offsetX = this.Width - this.paddingRight;
                    offsetY += maxHeight + this.gap;
                    maxHeight = 0;
                }
            }
        } else if (this.alignX == "left" && this.alignY == "bottom") {
            let offsetX = this.paddingLeft;
            let offsetY = this.Height - this.paddingBottom;
            let maxHeight = 0;
            for (let i = 0; i < this.childViews.length; i++) {
                const view = this.childViews[i];
                view.Top = offsetY - view.Height;
                view.Left = offsetX;
                offsetX += view.Width + this.gap;

                let tempMaxWidth = maxHeight;
                if (view.Height > maxHeight) {
                    maxHeight = view.Height;
                }

                if (
                    offsetX > this.Width - this.paddingRight &&
                    offsetX - this.gap > this.Width - this.paddingRight
                ) {
                    i--;
                    offsetX = this.paddingLeft;
                    if (tempMaxWidth != maxHeight) {
                        maxHeight = tempMaxWidth;
                    }
                    offsetY -= maxHeight + this.gap;
                    maxHeight = 0;
                    continue;
                }

                if (offsetX >= this.Width - this.paddingRight) {
                    offsetX = this.paddingLeft;
                    offsetY -= maxHeight + this.gap;
                    maxHeight = 0;
                }
            }
        } else if (this.alignX == "right" && this.alignY == "bottom") {
            let offsetX = this.Width - this.paddingRight;
            let offsetY = this.Height - this.paddingBottom;

            let maxHeight = 0;

            for (let i = 0; i < this.childViews.length; i++) {
                const view = this.childViews[i];
                view.Top = offsetY - view.Height;
                view.Left = offsetX - view.Width;
                offsetX -= view.Width + this.gap;

                let tempMaxWidth = maxHeight;
                if (view.Height > maxHeight) {
                    maxHeight = view.Height;
                }

                if (
                    offsetX < this.paddingLeft &&
                    offsetX + this.gap < this.paddingLeft
                ) {
                    i--;
                    offsetX = this.Width - this.paddingRight;
                    if (tempMaxWidth != maxHeight) {
                        maxHeight = tempMaxWidth;
                    }
                    offsetY -= maxHeight + this.gap;
                    maxHeight = 0;
                    continue;
                }

                if (offsetX <= this.paddingLeft) {
                    offsetX = this.Width - this.paddingRight;
                    offsetY -= maxHeight + this.gap;
                    maxHeight = 0;
                }
            }
        } else if (this.alignX == "center" && this.alignY == "top") {
            const rows = this.childToRows();

            for (let i = 0; i < rows.length; i++) {
                const row = rows[i];
                let lineWidth = this.calcWidth(row);
                let offsetX = (this.Width - lineWidth) / 2;

                for (let j = 0; j < row.length; j++) {
                    const view = row[j];
                    view.Left = offsetX;
                    offsetX += view.Width + this.gap;
                }
            }
        } else if (this.alignX == "center" && this.alignY == "bottom") {
            const rows = this.childToRows();
            let offsetY = this.Height - this.paddingBottom;
            for (let i = 0; i < rows.length; i++) {
                const row = rows[i];
                let lineWidth = this.calcWidth(row);
                let lineHeight = this.calcHeight(row);
                let offsetX = (this.Width - lineWidth) / 2;
                for (let j = 0; j < row.length; j++) {
                    const view = row[j];
                    view.Left = offsetX;
                    view.Top = offsetY - lineHeight;
                    offsetX += view.Width + this.gap;
                }
                offsetY -= lineHeight + this.gap;
            }
        } else if (this.alignX == "center" && this.alignY == "center") {
            const rows = this.childToRows();
            const totalHeight = this.getRowsHeight(rows);
            let offsetY = (this.Height - totalHeight) / 2;

            for (let i = 0; i < rows.length; i++) {
                const row = rows[i];
                let lineWidth = this.calcWidth(row);
                let lineHeight = this.calcHeight(row);
                let offsetX = (this.Width - lineWidth) / 2;
                for (let j = 0; j < row.length; j++) {
                    const view = row[j];
                    view.Left = offsetX;
                    view.Top = offsetY;
                    offsetX += view.Width + this.gap;
                }
                offsetY += lineHeight + this.gap;
            }
        } else if (this.alignX == "left" && this.alignY == "center") {
            const rows = this.childToRows();
            let offsetY = (this.Height - this.getRowsHeight(rows)) / 2;
            for (let i = 0; i < rows.length; i++) {
                const row = rows[i];
                // let lineWidth = this.calcWidth(row);
                let lineHeight = this.calcHeight(row);
                let offsetX = this.paddingLeft;
                for (let j = 0; j < row.length; j++) {
                    const view = row[j];
                    view.Left = offsetX;
                    view.Top = offsetY;
                    offsetX += view.Width + this.gap;
                }
                offsetY += lineHeight + this.gap;
            }
        } else if (this.alignX == "right" && this.alignY == "center") {
            const rows = this.childToRows();
            let offsetY = (this.Height - this.getRowsHeight(rows)) / 2;
            for (let i = 0; i < rows.length; i++) {
                const row = rows[i];
                let lineWidth = this.calcWidth(row);
                let lineHeight = this.calcHeight(row);
                let offsetX = this.Width - this.paddingRight - lineWidth;
                for (let j = 0; j < row.length; j++) {
                    const view = row[j];
                    view.Left = offsetX;
                    view.Top = offsetY;
                    offsetX += view.Width + this.gap;
                }
                offsetY += lineHeight + this.gap;
            }
        }
    }

    private childToRows(): QUIView[][] {
        let rows: QUIView[][] = [];
        let row: QUIView[] = [];
        let offsetX = this.paddingLeft;
        let offsetY = this.paddingTop;
        let maxHeight = 0;

        for (let i = 0; i < this.childViews.length; i++) {
            const view = this.childViews[i];
            view.Top = offsetY;
            view.Left = offsetX;
            offsetX += view.Width + this.gap;
            row.push(view);

            let tempMaxWidth = maxHeight;
            if (view.Height > maxHeight) {
                maxHeight = view.Height;
            }

            if (
                offsetX > this.Width - this.paddingRight &&
                offsetX - this.gap > this.Width - this.paddingRight
            ) {
                i--;
                row.pop();
                offsetX = this.paddingLeft;
                if (tempMaxWidth != maxHeight) {
                    maxHeight = tempMaxWidth;
                }
                offsetY += maxHeight + this.gap;
                rows.push(row);
                maxHeight = 0;
                row = [];
                continue;
            }

            if (offsetX >= this.Width - this.paddingRight) {
                offsetX = this.paddingLeft;
                offsetY += maxHeight + this.gap;
                rows.push(row);
                maxHeight = 0;
                row = [];
            }
        }
        if (row.length > 0) {
            rows.push(row);
        }
        return rows;
    }

    private getRowsHeight(rows: QUIView[][]): number {
        let height = 0;
        if (rows.length > 0) {
            for (let i = 0; i < rows.length; i++) {
                const row = rows[i];
                height += this.calcHeight(row);
            }
        }
        return height;
    }

    public remove(view: QUIView, destroy?: boolean): void {
        super.remove(view, destroy);
        this.reLayout();
    }

    add(child: QUIView) {
        super.add(child);
        this.reLayout();
        return this;
    }
}
